package server;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class DownloadServer implements Runnable {
	final static String directoryPath = System.getProperty("user.home") + File.separator + "lanyard_server";
	String fileName = ""; // the file to download
	long timestamp;
	public int port; // the port the server will serve the file from
	ServerSocket servSock;
	// HACK: 0 means download, 1 means upload
	public short operation = 0;
	
	Socket socket;
	OutputStream binaryWriter;
	InputStream binaryReader;
	ServerDirectory directory;
	
	public DownloadServer(String fileName, long timestamp, int port, ServerDirectory directory) throws IOException {
		servSock = new ServerSocket(port);
		this.port = port;
		this.fileName = fileName;
		this.directory = directory;
		this.timestamp = timestamp;
	}

	public void run() {
		try {
			// Create a server socket to accept client connection requests
			System.out.println("Socket setup on port"+ port);

			Socket clntSock = servSock.accept();     // Get client connection
			this.socket = clntSock;
			binaryWriter = socket.getOutputStream();
			binaryReader = socket.getInputStream();
			
			if (operation == 0) {
				// dispatcher: launch threads based on incoming command
				FileInputStream fileStream = null;
				System.out.println("Trying download: "+ directoryPath + File.separator + fileName);
				try {
					fileStream = new FileInputStream(directoryPath + File.separator + fileName);
					sendBytes(fileStream);
					fileStream.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
	
				System.out.println("Finished downloading file "+ fileName +" for " +
						clntSock.getInetAddress().getHostAddress() + " on port " +
						port);
			} else {
				FileOutputStream fileStream = null;
				try {
					System.out.println("Accepting file upload: "+ directoryPath + File.separator + fileName);
					fileStream = new FileOutputStream(directoryPath + File.separator + fileName);
					int bytesRead;
					byte[] buffer = new byte[1024];
					while ((bytesRead = binaryReader.read(buffer)) != -1) {
						fileStream.write(buffer, 0, bytesRead);
					}
					fileStream.flush();
					fileStream.close();
					System.out.println("Finished file uploadload: "+ fileName);
					
					if (!new File(fileName).setLastModified(this.timestamp)) {
						util.Logger.Debug("Failed to override timestamp ("+timestamp+") on upload "+ fileName);
					}
					
					directory.addFile(fileName);
					
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			
			// kill the connection since this port needs to be reused
			binaryReader.close();
			binaryWriter.close();
			clntSock.close();
			servSock.close();

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	private void sendBytes(FileInputStream fileStream) throws IOException {
		int bytesRead;
		byte[] buffer = new byte[256];
		while ((bytesRead = fileStream.read(buffer)) != -1) {
			binaryWriter.write(buffer, 0, bytesRead);
		}
		socket.shutdownOutput();
	}
}